home *** CD-ROM | disk | FTP | other *** search
- Path: news.th-darmstadt.de!news
- From: Enno Sandner <enno@intellektik.informatik.th-darmstadt.de>
- Newsgroups: comp.lang.c++
- Subject: Re: Smart Pointer Implementation & question
- Date: Tue, 16 Jan 1996 10:16:59 +0100
- Organization: Fachbereich Informatik, TH Darmstadt
- Message-ID: <30FB6D0B.167EB0E7@intellektik.informatik.th-darmstadt.de>
- References: <4dfe36$d99@grid.direct.ca>
- NNTP-Posting-Host: kitz.intellektik.informatik.th-darmstadt.de
- Mime-Version: 1.0
- Content-Type: text/plain; charset=us-ascii
- Content-Transfer-Encoding: 7bit
- X-Mailer: Mozilla 2.0b5 (X11; I; SunOS 4.1.3 sun4m)
-
- Ken Clark wrote:
- >
- > Hi. I have implemented a reference counting smart pointer class. It works
- > well, except that I can't get a basic behavior of normal pointers: automatic
- > casting of subclass pointers. Consider class shape and subclass circle. I
- > can do
- > shape *s;
- > circle *c;
- > ...
- > s = c;
- >
- > What I want to be able to do (with the same semantics)
- > RCPtr<shape> s;
- > RCPtr<circle> c;
- > ...
- > s = c;
- >
- > I think I understand why I can't do this (Stoustrup's square peg in round hole
- > analogy). My question is, how do I get this behavior if that is what I want?
- >
- >
- > I have included the class below. Any other suggestions on how to improve it
- > are appreciated. Feel free to use the class in your code if you like.
- >
- > Thanks,
- >
- > - Ken
- >
- > template <class T>
- > class RCPtr {
- > struct RCPtrRep {
- > T *p;
- > unsigned count;
- > RCPtrRep(T* ip = 0) { p = ip; count = 1; }
- > ~RCPtrRep() { delete p; }
- > } *rep;
- > public:
- > RCPtr(T *ip = 0) { rep = new RCPtrRep(ip); }
- > RCPtr& operator=(T *ip)
- > {
- > RCPtr::~RCPtr();
- > rep = new RCPtrRep(ip);
- > return *this;
- > }
- > RCPtr& operator=(const RCPtr& rip)
- > {
- > rip.rep->count++;
- > RCPtr::~RCPtr();
- > rep = rip.rep;
- > return *this;
- > }
- > ~RCPtr()
- > {
- > if (--rep->count == 0) delete rep;
- > }
- > T *operator->() { return (T *)rep->p; }
- > T& operator*() { return *(T *)rep->p; }
- > };
-
- I think in theory (ie. according to the DWP) you can have a templated
- conversion operator in the class:
-
- template<class T> class RCPtr {
- ...
-
- template<class S> operator RCPtr<S>() const {
- S* s=dynamic_cast<S*>(rep->p);
- return RCPtr<S>(s ? new S(*s) : 0);
- }
- };
-
- Anyway this will not work on any compiler these days.
- A workarround is an auxilary templated function, that does the job.
- Both solutions exspect that the RCPtr class can properly handle
- null-pointers.
- In addition your class can lead to unwanted modifications. For example:
-
- struct A {
- A() : valid_(true) {}
- bool valid_;
- };
-
- int main()
- {
- RCPtr<A> pa1(new A());
- RCPtr<A> pa2=pa1;
- pa1->valid_=false;
-
- // pa1->valid_==false && pa2->valid_==false
- }
-
- will modify _both_ instances.
- Can can remove this problem if you clone the maintained instance every
- time
- the wrapper returns a non-const pointer or reference to it.
-
- Enno
-